/* ====================================================================
 * 作者-------  支叶认知
 * 创作时间---  20220403
 * 功能-------  第三方接口示例（ThirdLib.c 定义应用程序的导出函数）
 * 运行环境---  长沙思知所提供的自然语运行环境
 */
//====================================================================

#include "ThirdBasics.h"

//=======初次调用库被执行函数=======================
void Thirdlib_Init(void *p)
{
	printf("Thirdlib_Init\n");
}

//=======结束库被调执行函数===========================
void Thirdlib_DeInit(void *p)
{
	printf("Thirdlib_DeInit\n");
}

//==========================================================
void LoadBoolInUnit(EXP_UNIT* &pUnit, int result)
{
	if(pUnit)
		BAS_CleanUnitData(pUnit);
	else
		pUnit = BAS_CreateUnit();
	pUnit->type = TYPE_NUM;
	pUnit->tval = NUM_BOOL;
	pUnit->Result = result;
}

void LoadNumInUnit(EXP_UNIT* &pUnit,INUM iNum)
{
	if(pUnit)
		BAS_CleanUnitData(pUnit);
	else
		pUnit = BAS_CreateUnit();
	pUnit->type = TYPE_NUM;
	pUnit->tval = NUM_NUM;
	pUnit->iNum = iNum;
}

void LoadDataInUnit(EXP_UNIT* &pUnit, int tval,const void *pBuf, int bLen)
{
	DATA_BUFSTR *pData = (DATA_BUFSTR *)gMalloc(sizeof(DATA_BUFSTR) + bLen + 1);
	memcpy(pData->pBuf, pBuf, bLen);
	pData->pBuf[bLen] = 0;
	pData->Len = bLen;
	if(pUnit)
		BAS_CleanUnitData(pUnit);
	else
		pUnit = BAS_CreateUnit();
	pUnit->type = TYPE_DATA;
	pUnit->tval = tval;
	pUnit->pBfS = pData;
}
//=============函数接口区============================
#include <stdint.h>
//=============================================================================================
typedef void (*FUNC_Keyboard)(int down, int key, int timems); //键盘l输入回调，down为1按下，0抬起，key为键值，timems为毫秒时间
typedef void (*FUNC_MouseLdown)(int x, int y); //左击 x,y 在窗体上的坐标
typedef void (*FUNC_MouseRdown)(int x, int y); //右击 x,y 在窗体上的坐标
typedef void (*FUNC_MouseMove)(int type, int x, int y); //type = 0 ,只是移动，type=1 按着左键移动，type=2，按着右键移动
//========================图形数据结构定义=====================================
//BEGIN_C_DECLS
typedef struct {
	uint8_t b;
	uint8_t g;
	uint8_t r;
	uint8_t a;
} rgba_t;

typedef union {
	rgba_t 	t;
	uint32_t	rgba;
}bitmap_trgb;


typedef struct {
	uint32_t w;
	uint32_t h;
	bitmap_trgb* data;
} bitmap_t;

//==================  pullwindow 返回结构定义========================
typedef struct
{
	void (*push)();			//推送屏显示
	void (*loadKeyMouse)(FUNC_Keyboard pKeybd, FUNC_MouseLdown pLdow, FUNC_MouseRdown pRdown, FUNC_MouseMove pMove); //按键与鼠标回调
	bitmap_t ui;
}UI_FuncSyn;


//---在代码中添加画窗操作参数tSysBaseUi
static bitmap_t tUiBase = { 0 };
//UI_FuncSyn tSysBaseUi = { 0 };
void (*ui_push)();

void UI_Clean()
{
	int max = tUiBase.w * tUiBase.h;
	while (max--) {
		tUiBase.data[max].rgba = 0;
	}
}
void UI_pointCol(int x, int y, uint32_t colour)
{
	if (x >= 0 && x < tUiBase.w && y >= 0 && y < tUiBase.h) {
		tUiBase.data[y * tUiBase.w + x].rgba = colour;
	}
}

void UI_pointR(int x, int y)
{
	if (x >= 0 && x < tUiBase.w && y >= 0 && y < tUiBase.h)
		tUiBase.data[y * tUiBase.w + x].t.r = 255;
}

void UI_pointG(int x, int y)
{
	if (x >= 0 && x < tUiBase.w && y >= 0 && y < tUiBase.h)
		tUiBase.data[y * tUiBase.w + x].t.g = 255;
}

void UI_pointB(int x, int y)
{
	if (x >= 0 && x < tUiBase.w && y >=0 && y < tUiBase.h)
		tUiBase.data[y * tUiBase.w + x].t.b = 255;
}

#define F_PRECISE 256	//校准参数精度
void UI_lineR(int xs, int ys, int xe, int ye)
{
	int w, h, max;
	int iw, ih;
	if (xe >= xs) {
		if (xe < 0 || xs >= tUiBase.w) return;
		w = xe - xs; iw = w;
		if (xs < 0) xs = 0;
		if (xe > tUiBase.w) xe = tUiBase.w;
	}
	else {
		if (xs < 0 || xe >= tUiBase.w) return;
		w = xe - xs; iw = -w;
		if (xe < 0) xe = 0;
		if (xs > tUiBase.w) xs = tUiBase.w;
	}
	if (ye >= ys) {
		if (ye < 0 || ys >= tUiBase.h) return;
		h = ye - ys; ih = h;
		if (ys < 0) ys = 0;
		if (ye > tUiBase.h) ye = tUiBase.h;
	}
	else {
		if (ys < 0 || ye >= tUiBase.h) return;
		h = ye - ys; ih = -h;
		if (ye < 0) ye = 0;
		if (ys > tUiBase.h) ys = tUiBase.h;
	}
	if (iw > ih) max = iw;
	else max = ih;
	//---------------------------------
	int wm, hm;
	wm = (w * F_PRECISE) / max;
	hm = (h * F_PRECISE) / max;
	xs *= F_PRECISE; ys *= F_PRECISE;
	w = tUiBase.w;
	while (max--) {
		tUiBase.data[((ys + (F_PRECISE / 2)) / F_PRECISE) * w + ((xs + (F_PRECISE / 2)) / F_PRECISE)].t.r = 255;
		xs += wm; ys += hm;
	}
}

typedef struct {
	uint16_t x;
	uint16_t y;
} gPOINT;

gPOINT savepoint[1024];
int maxpint = 0;
//----如果需要鼠标功能定义以下函数（根据需求选定）-----------------
void MouseLdown(int x, int y) //左击 x,y 在窗体上的坐标
{
	printf("Ldown(%d,%d)->%d\n",x,y, maxpint);
	UI_pointR(x, y);
	ui_push();

	savepoint[maxpint].x = x;
	savepoint[maxpint].y = y;
	maxpint++;
	//处理鼠标左击代码
}

#define _USE_MATH_DEFINES
#include <math.h>
#define DEGREE 3
// 多项式回归的系数
double  coefficients[DEGREE + 1] = { 0.0 };

// Electricity Values through Voltage
float Get_Val(float voltage) {
	double capacity = 0.0;
	for (int i = 0; i <= DEGREE; i++) {
		capacity += coefficients[i] * pow(voltage, i);
	}
	return capacity;
}

void Cal_CurveCoef()
{
	double voltages, capacities;
	int vMax = maxpint;
	// 多项式回归的矩阵
	double matrix[DEGREE + 1][DEGREE + 2];
	for (int i = 0; i <= DEGREE; i++) {
		for (int j = 0; j <= DEGREE + 1; j++) {
			matrix[i][j] = 0.0;
		}
	}
	// 构建多项式回归的矩阵
	for (int i = 0; i <= DEGREE; i++) {
		for (int j = 0; j <= DEGREE; j++) {
			for (int k = 0; k < vMax; k++) {
				voltages = savepoint[k].x;
				matrix[i][j] += pow(voltages, i + j);
			}
		}
		for (int k = 0; k < vMax; k++) {
			voltages = savepoint[k].x;
			capacities= savepoint[k].y;
			matrix[i][DEGREE + 1] += capacities * pow(voltages, i);
		}
	}
	// 解多项式回归的矩阵方程
	for (int i = 0; i <= DEGREE; i++) {
		for (int j = i + 1; j <= DEGREE; j++) {
			double ratio = matrix[j][i] / matrix[i][i];
			for (int k = 0; k <= DEGREE + 1; k++) {
				matrix[j][k] -= ratio * matrix[i][k];
			}
		}
	}
	// 回代求解多项式回归的系数
	for (int i = DEGREE; i >= 0; i--) {
		coefficients[i] = matrix[i][DEGREE + 1];
		for (int j = i + 1; j <= DEGREE; j++) {
			coefficients[i] -= matrix[i][j] * coefficients[j];
		}
		coefficients[i] /= matrix[i][i];
	}
}

void MouseRdown(int x, int y) //右击 x,y 在窗体上的坐标
{//处理鼠标右击代码
	UI_Clean();
	for (int i = 1; i < maxpint; i++) {
		UI_lineR(savepoint[i-1].x, savepoint[i-1].y,savepoint[i].x, savepoint[i].y);
	}
	__int64 timer1, timer2,timer3;
	timer1=GetTickCount64();
	Cal_CurveCoef();
	timer2 = GetTickCount64();
	for (x = 0; x < tUiBase.w; x++) {
		UI_pointG(x, Get_Val(x));
	}
	timer3 = GetTickCount64();
	ui_push();
	printf("time1[%lld],time2[%lld]\n", timer2-timer1, timer3- timer2);
}
void MouseMove(int type, int x, int y) //type = 0 ,只是移动，type=1 按左键移动，type=2，按右键移动
{//处理鼠标移动代码
	if (type == 1) {
		for (double q = 0; q < (M_PI * 2); q += 1 / (M_PI * 2 * 100)) {
			UI_pointB(x + sin(q) * 100, y + cos(q) * 100);
		}
		ui_push();
	}
	else if (type == 2) {
		for (double q = 0; q < (M_PI * 2); q += 1 / (M_PI * 2 * 100)) {
			UI_pointR(x + sin(q) * 150, y + cos(q) * 70);
		}
		ui_push();
	}
}

void In_Keyboard(int down, int key, int timems)
{
	if (down == 1 && maxpint > 0) {
		maxpint = 0;
		UI_Clean();
		ui_push();
	}
}
//----------Y语言引用函数定义---------------------------------
int FunPullUiBase(EnvP pENV, EXP_UNIT*& pInOutPar)	//(&UiBase)
{
	EXP_UNIT* pData = BAS_ParsingUnit(pInOutPar);
	if (pData == NULL || pData->type != TYPE_DATA || pData->tval != DATA_BUF) return -5;
	if (pData->pBfS->Len < sizeof(UI_FuncSyn)) {
		LoadBoolInUnit(pInOutPar, false);
		return 1;
	}
	printf("PullUiBase %d\n", pData->pBfS->Len);
	UI_FuncSyn* pSyn = (UI_FuncSyn*)pData->pBfS->pBuf;
	tUiBase.w = pSyn->ui.w;
	tUiBase.h = pSyn->ui.h;
	tUiBase.data = pSyn->ui.data;  //后面通过 tSysBaseUi.ui.data 修改显示内容
	ui_push = pSyn->push; //后面 通过 执行 ：tSysBaseUi.push()推动显示刷新
	//------需要鼠标功能需要执行回调功能加载---------------
	(*pSyn->loadKeyMouse)(In_Keyboard,MouseLdown, MouseRdown, MouseMove);
	LoadBoolInUnit(pInOutPar, true);
	return 1;	//只返回一个参数
}


int FunDrawPoint(EnvP pENV, EXP_UNIT*& pInOutPar)	//(x,y,colour)
{
	EXP_UNIT* pX = BAS_ParsingUnit(pInOutPar);
	if (pX == NULL || pX->type != TYPE_NUM) return -5;
	EXP_UNIT* pY = BAS_ParsingUnit(pInOutPar->pNext);
	if (pY == NULL || pY->type != TYPE_NUM) return -5;
	EXP_UNIT* pCol = BAS_ParsingUnit(pInOutPar->pNext->pNext);
	uint32_t col;
	if (pCol != NULL && pCol->type == TYPE_NUM)
		col = pCol->iVal;
	else col = ((rand()<<8)|rand());
	UI_pointCol(pX->iNum, pY->iNum, col);
	ui_push();
	return 0;
}

int FunGetSin(EnvP pENV, EXP_UNIT*& pInOutPar)	//(angle)
{
	EXP_UNIT* angle = BAS_ParsingUnit(pInOutPar);
	if (angle == NULL || angle->type != TYPE_NUM) return -5;
	LoadNumInUnit(pInOutPar, sin(angle->iNum * M_PI / 180));
	return 1;
}

int FunGetCos(EnvP pENV, EXP_UNIT*& pInOutPar)	//(angle)
{
	EXP_UNIT* angle = BAS_ParsingUnit(pInOutPar);
	if (angle == NULL || angle->type != TYPE_NUM) return -5;
	LoadNumInUnit(pInOutPar, cos(angle->iNum * M_PI / 180));
	return 1;
}




//=====================配置==================================================
//=========函数对应表(名称,功能，使用规则，最后以NULL结束)=================
const DEF_FUNC_Tbl gFuncTbl =
{
	FUNC_TYPE_I,	1,
	1,
	{
		"getuibase",	FunPullUiBase,
		"point",		FunDrawPoint,
		"sin",			FunGetSin,
		"cos",			FunGetCos,
		NULL,			NULL,	//结束行
	}
};
/*
开发者信息(JSON格式{id:var,id2:var2,....})说明：
ID 	：已注册的开发者编号（版权依据，贡献依据，收益凭证），没有可以无此项
公司	：个人开发者不需要填此项
作者	：开发者姓名
手机	：开发者手机号（贡献版权依据）
*/
const char sDeveloperInfo[] = "test ui";



//==============导出总接口：gTotalInterSet==================
extern const TOTAL_INTERFACE gTotalInterSet =
{
	sDeveloperInfo,
	NULL, //开发者证书
	{
		&gFuncTbl,
		NULL,	//结束行
	}
};




